home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
progutil
/
stdwin.zoo
/
alfa
/
event.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-18
|
6KB
|
340 lines
/* STDWIN -- EVENTS. */
#include "alfa.h"
/* There are three levels of event processing.
The lowest ('raw') level only inputs single characters.
The middle ('sys') level translates sequences of keys to menu shortcuts
and 'commands'.
The highest ('appl') level executes certain commands and can call the
interactive menu selection code. It also sets the window parameter.
For each level there are variants to wait or poll.
Additional routines to get from one level to another:
wmapchar: inspect key map and possibly convert char event
wsyscommand: execute/transform system menu
/* Raw event -- read one character. If blocking is FALSE,
don't read if trmavail() returns -1, meaning it can't tell whether
there is input or not. In that case only synchronous input works. */
static bool
wrawevent(ep, blocking)
EVENT *ep;
bool blocking;
{
if (!blocking && trmavail() <= 0)
return FALSE;
ep->u.character= trminput();
if (ep->u.character < 0) {
ep->type= WE_NULL;
return FALSE;
}
else {
ep->type= WE_CHAR;
return TRUE;
}
}
static void wmapchar(); /* Forward */
/* System event -- read a character and translate using the key map. */
bool
wsysevent(ep, blocking)
EVENT *ep;
bool blocking;
{
struct keymap mapentry;
if (!wrawevent(ep, blocking))
return FALSE;
/* Using a temporary to avoid a tahoe C compiler bug */
mapentry= _wprimap[ep->u.character & 0xff];
wmapchar(ep, mapentry);
return ep->type != WE_NULL;
}
/* Key map translation from raw event.
This may read more characters if the start of a multi-key sequence is
found. */
static void
wmapchar(ep, mapentry)
EVENT *ep;
struct keymap mapentry;
{
switch (mapentry.type) {
case SHORTCUT:
ep->type= WE_MENU;
ep->u.m.id= mapentry.id;
ep->u.m.item= mapentry.item;
break;
case SECONDARY:
if (wrawevent(ep, TRUE)) {
struct keymap *map;
struct keymap *altmap= NULL;
for (map= _wsecmap[mapentry.id];
map->type != SENTINEL;
++map) {
if (map->key == ep->u.character) {
wmapchar(ep, *map);
return;
}
else if (islower(ep->u.character) &&
map->key == toupper(ep->u.character))
altmap= map;
}
if (altmap != NULL) {
wmapchar(ep, *altmap);
return;
}
}
trmbell();
ep->type= WE_NULL;
break;
}
}
void
wgoto(ep, type)
EVENT *ep;
int type;
{
int h, v;
trmsense(&v, &h);
if (v >= 0) {
WINDOW *win;
for (win= &winlist[1]; win < &winlist[MAXWINDOWS]; ++win) {
if (win->open && v >= win->top && v < win->bottom) {
if (win == front) {
ep->type= type;
ep->u.where.h= h;
ep->u.where.v= v + win->offset;
ep->u.where.clicks= 1;
ep->u.where.button= 1;
ep->u.where.mask=
(type == WE_MOUSE_UP ? 0 : 1);
return;
}
wsetactive(win);
break;
}
}
}
ep->type= WE_NULL;
}
void
wmouseup(ep)
EVENT *ep;
{
int h, v;
trmsense(&v, &h);
if (v < 0)
ep->type= WE_NULL;
else {
ep->type= WE_MOUSE_UP;
ep->u.where.h= h;
ep->u.where.v= v + front->offset;
ep->u.where.clicks= 1;
ep->u.where.button= 1;
ep->u.where.mask= 0;
}
}
static void wdoupdates(); /* Forward */
/* Application event. */
static EVENT ebuf;
void
wungetevent(ep)
EVENT *ep;
{
ebuf= *ep;
}
bool
wpollevent(ep)
EVENT *ep;
{
return wevent(ep, FALSE);
}
void
wgetevent(ep)
EVENT *ep;
{
(void) wevent(ep, TRUE);
}
static bool
wevent(ep, blocking)
EVENT *ep;
bool blocking;
{
static int lasttype= WE_NULL;
if (ebuf.type != WE_NULL) {
*ep= ebuf;
ebuf.type= WE_NULL;
return TRUE;
}
ep->type= WE_NULL;
ep->window= NULL;
if (lasttype == WE_MOUSE_DOWN)
wmouseup(ep);
while (ep->type == WE_NULL) {
if (front != wasfront) {
if (wasfront != NULL) {
ep->type= WE_DEACTIVATE;
ep->window= wasfront;
wasfront= NULL;
}
else {
menubarchanged();
ep->type= WE_ACTIVATE;
wasfront= front;
}
}
else {
if (trmavail() <= 0)
wdoupdates(ep);
if (ep->type == WE_NULL) {
/* Remove this call if no select() exists */
if (_w_checktimer(ep, blocking))
break;
if (!wsysevent(ep, blocking)) {
ep->type= WE_NULL;
break;
}
if (ep->type == WE_MENU && ep->u.m.id == 0)
wsyscommand(ep);
}
}
}
if (ep->window == NULL && front != syswin)
ep->window= front;
lasttype= ep->type;
return ep->type != WE_NULL;
}
void
wsyscommand(ep)
EVENT *ep;
{
ep->type= WE_NULL;
switch (ep->u.m.item) {
default:
if (ep->u.m.item <= LAST_CMD) {
ep->type= WE_COMMAND;
ep->u.command= ep->u.m.item - FIRST_CMD;
}
break;
case NEXT_WIN:
_wselnext();
break;
case PREV_WIN:
_wselprev();
break;
case SUSPEND_PROC:
_wsuspend();
break;
case REDRAW_SCREEN:
_wredraw();
break;
case MOUSE_DOWN:
case MOUSE_UP:
wgoto(ep, ep->u.m.item - MOUSE_DOWN + WE_MOUSE_DOWN);
break;
case LITERAL_NEXT:
_wlitnext(ep);
break;
case MENU_CALL:
menuselect(ep);
break;
}
}
/* Flush output and place cursor. */
void
wflush()
{
int y= front->curv - front->offset;
int x= front->curh;
if (front->curv < 0 || y < front->top || y >= front->bottom) {
y= front->top;
if (y > 0)
--y;
x= 0;
}
else if (x < 0)
x= 0;
else if (x >= columns)
x= columns-1;
trmsync(y, x);
}
/* Process pending window updates.
If a window has no draw procedure, a WE_DRAW event is generated instead. */
static void
wdoupdates(ep)
EVENT *ep;
{
WINDOW *win;
int left, top, right, bottom;
for (win= winlist; win < &winlist[MAXWINDOWS]; ++win) {
if (win->open) {
if (win->top > 0 && !uptodate[win->top - 1])
wdrawtitle(win);
if (wgetchange(win, &left, &top, &right, &bottom)) {
if (win->drawproc == NULL) {
ep->type= WE_DRAW;
ep->window= win;
ep->u.area.left= left;
ep->u.area.top= top;
ep->u.area.right= right;
ep->u.area.bottom= bottom;
return;
}
else {
wbegindrawing(win);
(*win->drawproc)(win,
left, top, right, bottom);
wenddrawing(win);
}
}
}
}
wflush();
}
void
_wlitnext(ep)
EVENT *ep;
{
(void) wrawevent(ep, TRUE);
}